#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "raylib.h"
#include "pub_lib.h"
#include "FreeImage.h"
#include "image.h"
#include "dpi_algo.h"

const int screenWidth = 1024;
const int screenHeight = 768;

cpu_image effect_data;
run_state gstate = STATE_IDLE;

void* right_plan = NULL; //right image FFT plan
float* gimage_data = NULL; //gimage_data[h][w]
fftwf_complex* gout_data = NULL;

char* hint_right = NULL;
char hint_left[128] = "image size";

char rectangle_image[] = "Fig0424(a)(rectangle).tif";  //4.13
char changed_rectangle[] = "Fig0425(a)(translated_rectangle).tif"; //4.13
char woman_image[] = "Fig0427(a)(woman).tif"; //4.14
char spatial2freq_image[] = "Fig0438(a)(bld_600by600).tif"; //4.15
char lp_image[] = "Fig0333(a)(test_pattern_blurring_orig).tif"; //4.16 - 4.18
char hp_thumb[] = "Fig0457(a)(thumb_print).tif"; //4.19
char hp_lapace[] = "Fig0338(a)(blurry_moon).tif"; //4.20
char hp_highboost[] = "Fig0459(a)(orig_chest_xray).tif"; //4.21
char bh_notch[] = "Fig0464(a)(car_75DPI_Moire).tif"; //4.23

#define MAX_CMD_NUM 6
const char command_str_en[MAX_CMD_NUM][MAX_HINT_STRING_LEN] =
{
	"1. rectangle spectrum", //example 4.13
	"2. rebuld from phase angle", //4.14
	"3. spatial mask to freq", //4.15
	"4. freq: low pass", //4.16 - 4.18
	"5. freq: high pass", //4.19 - 4.21
	"6. freq: band pass" //4.23
};

const char command_str_cn[MAX_CMD_NUM][MAX_HINT_STRING_LEN] =
{
	"1. 长方形块频谱",
	"2. 从相角恢复图片",
	"3. 从时域滤波到频域",
	"4. 频域低通滤波",
	"5. 频域高通滤波",
	"6. 频域带通滤波"
};

void init_effect_data(void)
{
	memset(&effect_data, 0, sizeof(cpu_image));
	effect_data.win_width = screenWidth;
	effect_data.win_height = screenHeight;
	effect_data.fb_pixels = effect_data.win_width * effect_data.win_height;
	effect_data.startx = 10;
	effect_data.starty = 30;
	effect_data.left_max = get_max_pixel(screenWidth, 0.3f);
	effect_data.right_max = get_max_pixel(screenWidth, 0.7f);
	effect_data.right_image_max = effect_data.right_max;;

	effect_data.split_line = effect_data.startx + effect_data.left_max + 5;
	effect_data.lx = effect_data.startx;
	effect_data.rx = effect_data.split_line + 5;
}

void init_fb(void)
{
	effect_data.frame_buf = calloc(effect_data.fb_pixels, sizeof(Color));
}

/*
 * 打开图片，读入图片数据
 * 原始图片信息:  ori
 * 左边显示的小图片: left
 * 右边显示的大图片: right
 * 右边显示的大图片的更改后的数据: rchg
 * 右边显示的大图片，中间计算的结果：rchg_data
 * */
int init_effect(char* path, int right_window_num)
{
	effect_data.right_window_num = right_window_num;
	const char* ext = GetFileExtension(path);

	FIBITMAP* ori;
	ori = open_img(path);
	if (!ori)
		return -1;
	if (!strcmp(ext, ".tif")) {
		read_img(ori, &effect_data);
		if (effect_data.format != PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) {
			printf("only support [0, 255] 1 byte TIF image\n");
			close_img(ori);
			return -1;
		}
	}
	effect_data.show_histo = 0;
	effect_data.order = 0;
	effect_data.ori = (void*)ori;
	effect_data.left = (void*)ori;
	effect_data.right = (void*)ori;
	//check if need scale of left image
	int max = effect_data.left_max; //最长或最宽不超过360
	int neww = max, newh = max;
		if ( effect_data.image_width > max || effect_data.image_height > max) {
		cal_scaled_val(max, effect_data.image_width, effect_data.image_height,\
				&neww, &newh);
		effect_data.left = FreeImage_Rescale(ori, neww, newh, FILTER_BILINEAR);
	}

	//update left_hint[]
	if(effect_data.ori != effect_data.left) {
		sprintf(hint_left, "ori:%dx%d  chg:%dx%d",\
			effect_data.image_width, effect_data.image_height,\
			neww, newh);
	} else {
		sprintf(hint_left, "ori:%d x %d",\
			effect_data.image_width, effect_data.image_height);
	}

	//check if need scale of right image
	if(right_window_num == 1)
		effect_data.right_image_max = get_max_pixel(screenWidth, 0.7f);
	else
		effect_data.right_image_max = split_right_window(effect_data.win_width, 0.7f);

	max = effect_data.right_image_max;
	neww = effect_data.image_width;
	newh = effect_data.image_height;
	if (effect_data.image_width > max || effect_data.image_height > max) {
		cal_scaled_val_radix2(max, effect_data.image_width, effect_data.image_height, \
			&neww, &newh);
		effect_data.right = FreeImage_Rescale(ori, neww, newh, FILTER_BILINEAR);
	}

	effect_data.rchg = FreeImage_Copy(effect_data.right, 0, 0, neww, newh);
	effect_data.pri  = FreeImage_Copy(effect_data.right, 0, 0, neww, newh);

	//int data[w][h]
	effect_data.rchg_data = calloc(neww * newh, sizeof(float));

	effect_data.image_size = GetPixelDataSize(effect_data.image_width,\
		effect_data.image_height, effect_data.format);
	effect_data.pix_len = get_pixel_bytes(effect_data.image_width,\
		effect_data.image_height, effect_data.image_size);

	right_plan = fft_init(neww, newh, &gimage_data, &gout_data);
	return 0;
}

void unload_image(void)
{
	if(effect_data.left != effect_data.ori)
		close_img(effect_data.left);
	if(effect_data.right != effect_data.ori)
		close_img(effect_data.right);
	if(effect_data.ori)
		close_img(effect_data.ori);
	if(effect_data.rchg)
		close_img(effect_data.rchg);
	if(effect_data.pri)
		close_img(effect_data.pri);

	if(effect_data.rchg_data)
		free(effect_data.rchg_data);
	if (right_plan)
		fft_exit(right_plan);
}

void destroy_effect(void)
{
	free(effect_data.frame_buf);
	unload_image();
}

void switch_next_image(char* filename, int right_window_num)
{
	int ret;
	char path[256];

	clear_fb(&effect_data, RAYWHITE);
	unload_image();
	get_full_path(IMAGE_PATH, filename, path);
	ret = init_effect(path, right_window_num);
	if (ret)
		return;
	show_image(effect_data.left, &effect_data,\
		effect_data.startx, effect_data.starty);
}

void handle_key_down(void)
{
	
}

void handle_key_up(void)
{
}

/*
 * int s[h*w]：原始频谱
 * BYTE data[h*w]: 归一化后的数据
 * */
void calc_scaled_spectrum(FIBITMAP* dib, float *s, BYTE *data,\
	int center, fft_show_type type)
{
	int w, h;
	w = FreeImage_GetWidth(dib);
	h = FreeImage_GetHeight(dib);

	if(center)
		init_image_center_data(dib, gimage_data);
	else
		init_image_data(dib, gimage_data);

	fft_r2c(right_plan, gimage_data, gout_data);
	calc_fft_spectrum(gout_data, s, w, h);

	if(type == FFT_SHOW_NORMAL)
		scale_float_data(s, data, w * h);
	else
		log_float_data(s, data, w * h);
}

//4.24
void effect_rectangle(void)
{
	switch_next_image(rectangle_image, 4);

	int w, h;
	w = FreeImage_GetWidth(effect_data.right);
	h = FreeImage_GetHeight(effect_data.right);
	BYTE* spectrum = (BYTE*)malloc(w * h);
	float *s = malloc(w * h * sizeof(float));

	draw_right_image(effect_data.rchg, 1);
	//FFT
	calc_scaled_spectrum(effect_data.rchg, s, spectrum, 0, FFT_SHOW_NORMAL);
	draw_right_data(spectrum, 2);

	//ori * (-1) ^ (x + y)
	calc_scaled_spectrum(effect_data.rchg, s, spectrum, 1, FFT_SHOW_NORMAL);
	draw_right_data(spectrum, 3);

	//logF
	log_float_data(s, spectrum, w * h);
	draw_right_data(spectrum, 4);

	free(spectrum);
	free(s);
}

//4.25
FIBITMAP* gchg = NULL;
FIBITMAP* gchg_rotate = NULL;

void calc_scaled_angle(FIBITMAP* dib, float* s, BYTE* data)
{
	int w, h;
	w = FreeImage_GetWidth(dib);
	h = FreeImage_GetHeight(dib);

	//ori * (-1) ^ (x + y)
	init_image_center_data(dib, gimage_data);
	fft_r2c(right_plan, gimage_data, gout_data);
	calc_fft_angle(gout_data, s, w, h);
	scale_float_data(s, data, w * h);
}

void effect_next_rectangle(void)
{
	clear_fb_right(&effect_data, RAYWHITE);

	char path[256];
	get_full_path(IMAGE_PATH, changed_rectangle, path);
	FIBITMAP* ori;
	ori = open_img(path);

	int w, h;
	w = FreeImage_GetWidth(effect_data.right);
	h = FreeImage_GetHeight(effect_data.right);
	gchg = FreeImage_Rescale(ori, w, h, FILTER_BILINEAR);
	gchg_rotate = FreeImage_RotateEx(effect_data.right,\
		-45, 0, 0, w/2, h/2, TRUE);
	close_img(ori);

	//show spectrum
	BYTE* spectrum = (BYTE*)malloc(w * h);
	float *s = malloc(w * h * sizeof(float));

	draw_right_image(gchg, 1);
	calc_scaled_spectrum(gchg, s, spectrum, 1, FFT_SHOW_LOG);
	draw_right_data(spectrum, 2);

	//show translation and rotated images
	draw_right_image(gchg_rotate, 3);
	calc_scaled_spectrum(gchg_rotate, s, spectrum, 1, FFT_SHOW_LOG);
	draw_right_data(spectrum, 4);

	free(s);
	free(spectrum);
}

//4.26
void effect_rectangle_phase_angle(void)
{
	clear_fb_right(&effect_data, RAYWHITE);

	int w, h;
	w = FreeImage_GetWidth(effect_data.right);
	h = FreeImage_GetHeight(effect_data.right);
	BYTE* angles = (BYTE*)malloc(w * h);
	float *a = malloc(w * h * sizeof(float));

	calc_scaled_angle(effect_data.rchg, a, angles);
	draw_right_data(angles, 1);

	calc_scaled_angle(gchg, a, angles);
	draw_right_data(angles, 2);

	calc_scaled_angle(gchg_rotate, a, angles);
	draw_right_data(angles, 3);

	free(a);
	free(angles);
	close_img(gchg);
	close_img(gchg_rotate);
}

void filter_and_show(fftwf_complex* filter, FIBITMAP* dib,
	int P, int Q, int window)
{
	int w, h;
	w = FreeImage_GetWidth(dib);
	h = FreeImage_GetHeight(dib);

	//filter image at frequency domain
	BYTE* image = malloc(w * h);
	init_image_datab(dib, image);
	float* filtered_image = malloc(w * h * sizeof(float));

	filter_freq_domain(image, w, h, filter, P, Q, filtered_image);

	//show filtered image
	scale_float_data(filtered_image, image, w * h);
	draw_right_data(image, window);
	//for future use
	memcpy(gimage_data, filtered_image, (w * h * sizeof(float)));

	//free resources
	fftwf_free(filter);
	free(image);
	free(filtered_image);
}

static void show_lp_figures(int P, int Q, freq_filter_type type)
{
	float rc[4] = {10, 30, 60, 460};
	int i;
	fftwf_complex* filter;

	for(i = 0; i < 4; i++){
		filter = lpfilter(rc[i], P, Q, type, 2);
		filter_and_show(filter, effect_data.right, P, Q, i + 1);
	}
}

static void effect_lowpass(void)
{
	int P, Q;
	int w, h;
	w = FreeImage_GetWidth(effect_data.right);
	h = FreeImage_GetHeight(effect_data.right);
	filter_freq_newsize(w, h, w, h, &P, &Q);

	if(effect_data.order == 0) {
		//ILPF, Ideal
		gstate = STATE_WAIT_NEXT;
		effect_data.order = 1;
		hint_right = "Ideal LPF: press space key";
		show_lp_figures(P, Q, FREQ_FILTER_IDEAL);
	} else if(effect_data.order == 1) {
		effect_data.order = 2;
		hint_right = "Butterworth LPF: press space key";
		show_lp_figures(P, Q, FREQ_FILTER_BTW);
	} else if(effect_data.order == 2) {
		effect_data.order = 0;
		gstate = STATE_FINISH;
		hint_right = "Gaussian LPF: end";
		show_lp_figures(P, Q, FREQ_FILTER_GAUSSIAN);
	}
}

static void binary_image_data(FIBITMAP* dib, float* data)
{
	int w, h, y, x;
	w = FreeImage_GetWidth(dib);
	h = FreeImage_GetHeight(dib);
	unsigned char value;
	int index;
	for (y = 0; y < h; y++) {
		for (x = 0; x < w; x++) {
			index = get_window_index(y, x, w);
			if(data[index] < 0)
				value = 0;
			else
				value = 255;
			FreeImage_SetPixelIndex(dib, x, y, &value);
		}
	}
}

static void show_laplacian_filter(char* image_file)
{
	int P, Q;
	int w, h;

	//一般情况下，一个菜单只处理一张图片，这个菜单处理了3个不同的图片
	//switch_next_image 会把 order = 0，所以这里保存它的值，未来恢复
	int order = effect_data.order;
	switch_next_image(image_file, 1);
	FIBITMAP* dib = effect_data.rchg;

	w = FreeImage_GetWidth(dib);
	h = FreeImage_GetHeight(dib);
	filter_freq_newsize(w, h, w, h, &P, &Q);

	fftwf_complex* filter;
	//4.9-6, filter = H(u, v)
	filter = hpfilter(0, P, Q, FREQ_FILTER_LAPlACE, 0);

	BYTE* image = malloc(w * h);
	init_image_datab(dib, image);
	float* filtered_image = malloc(w * h * sizeof(float));
	//4.9-7, fill_image_data = gradient^2 f(x,y)
	filter_freq_domain(image, w, h, filter, P, Q, filtered_image);
	//set 0 if negative, reference ch3: laplacian filter in spatial domain
	int i, total = w * h;
	for(i = 0; i < total; i++) {
		if(filtered_image[i] < 0)
			filtered_image[i] = 0;
	}
	scale_float_data(filtered_image, image, w * h); //0 - 255
	//effect_data.pri = gradient^2 f(x,y)
	fill_image_data(effect_data.pri, image);
	//draw_right_image(effect_data.pri, 1);

	//4.9-8, g = f - gradient^2 f(x,y), c = -1
	image_add(dib, effect_data.pri, dib, -1);
	draw_right_image(dib, 1);

	effect_data.order = order;
	//free resources
	fftwf_free(filter);
	free(image);
	free(filtered_image);
}

/* 4.21
 * 1. D0 = 40，高斯滤波
 * 2. k1 = 0.5, k2 = 0.75, Highboost
 * 3. 直方图均衡
 * */
static void show_highboost_filter(char* image_file)
{
	int P, Q;
	int w, h;

	int order = effect_data.order;
	switch_next_image(image_file, 4);
	FIBITMAP* dib = effect_data.rchg;

	w = FreeImage_GetWidth(dib);
	h = FreeImage_GetHeight(dib);
	filter_freq_newsize(w, h, w, h, &P, &Q);

	fftwf_complex* filter;
	filter = hpfilter(40, P, Q, FREQ_FILTER_GAUSSIAN, 0);

	BYTE* image = malloc(w * h);
	init_image_datab(dib, image);
	float* filtered_image = malloc(w * h * sizeof(float));

	//show first image, Gaussian filter
	filter_freq_domain(image, w, h, filter, P, Q, filtered_image);
	scale_float_data(filtered_image, image, w * h);
	draw_right_data(image, 1);

	//figure2: high boost, k1=0.5, k2=0.75
	hpfilter_highboost(filter, 0.5, 0.75, P, Q);
	init_image_datab(dib, image); //restore image
	filter_freq_domain(image, w, h, filter, P, Q, filtered_image);
	scale_float_data(filtered_image, image, w * h);
	draw_right_data(image, 2);

	//figure3: histogram equalization
	fill_image_data(dib, image); //write data to image
	image_histogram_equa(dib, dib, NULL);
	draw_right_image(dib, 3);

	effect_data.order = order;
	//free resources
	fftwf_free(filter);
	free(image);
	free(filtered_image);
}

static void effect_highpass(void)
{
	int P, Q;
	int w, h;
	w = FreeImage_GetWidth(effect_data.right);
	h = FreeImage_GetHeight(effect_data.right);
	filter_freq_newsize(w, h, w, h, &P, &Q);

	fftwf_complex* filter;

	if(effect_data.order == 0) {
		//4.19
		gstate = STATE_WAIT_NEXT;
		effect_data.order = 1;
		hint_right = "Highpass filter: press space key";
		printf("高通滤波；阈值操作\n");

		//d0 = 50, n = 4, Butterworth filter
		filter = hpfilter(50, P, Q, FREQ_FILTER_BTW, 4);
		filter_and_show(filter, effect_data.right, P, Q, 1);

		binary_image_data(effect_data.rchg, gimage_data);
		draw_right_image(effect_data.rchg, 2);
	} else if(effect_data.order == 1) {
		effect_data.order = 2;
		hint_right = "Laplacian HPF: press space key";
		show_laplacian_filter(hp_lapace);
		printf("高通滤波，拉普拉斯算子\n");
	} else if(effect_data.order == 2) {
		effect_data.order = 3;
		gstate = STATE_FINISH;
		hint_right = "Highboost HPF: end";
		show_highboost_filter(hp_highboost);
	}
}

static ncenter measure_c[] = {
	{50, 42},
	{50, 82},
	{50, 166},
	{50, 202}
};

static notch_center center =
{
	4, measure_c
};

static void effect_notch(void)
{
	int w, h;
	FIBITMAP* dib = effect_data.right;
	w = FreeImage_GetWidth(dib);
	h = FreeImage_GetHeight(dib);

	//show spectrum
	BYTE* spectrum = (BYTE*)malloc(w * h);
	float *s = malloc(w * h * sizeof(float));

	calc_scaled_spectrum(dib, s, spectrum, 1, FFT_SHOW_LOG);
	draw_right_data(spectrum, 1);

	//show filter
	fftwf_complex* filter;
	//D0 = 9, n = 4
	float d0 = 9;
	filter = nrfilter(d0, &center, w, h, FREQ_FILTER_BTW, 4, 1);
	fft_rrmulti(filter, spectrum, s, w, h);
	scale_float_data(s, spectrum, w * h);
	draw_right_data(spectrum, 2);
	fftwf_free(filter);

	//figure 3, filtered image
	int P, Q;
	filter_freq_newsize(w, h, w, h, &P, &Q);
	float scale = Q / h;
	d0 = d0 * scale;
	notch_center* newc = change_center(&center, scale);
	filter = nrfilter(d0, newc, P, Q, FREQ_FILTER_BTW, 4, 0);
	free_center(newc);
	//filter = hpfilter(d0, P, Q, FREQ_FILTER_BTW, 4);
	filter_and_show(filter, dib, P, Q, 3);

	//figure4, final spectrum
	//gimage_data = filtered image
	scale_float_data(gimage_data, spectrum, w * h);
	fill_image_data(effect_data.rchg, spectrum);
	calc_scaled_spectrum(effect_data.rchg, s, spectrum, 1, FFT_SHOW_LOG);
	draw_right_data(spectrum, 4);

	free(s);
	free(spectrum);
}

void handle_key_space(void)
{
	if(gstate != STATE_WAIT_NEXT)
		return;

	switch(effect_data.cmd) {
		case 1:
			/* rectangle spectrum and phase angle */
			if(effect_data.order == 0) {
				effect_data.order = 1;
				hint_right = "spectrum: 4.25, press key space";
				effect_next_rectangle();
			} else if(effect_data.order == 1) {
				effect_data.order = 0;
				hint_right = "phase angle: 4.26";
				effect_rectangle_phase_angle();
				gstate = STATE_FINISH;
			}
			break;
		case 4:
			effect_lowpass();
			break;
		case 5:
			effect_highpass();
			break;
		default:
			break;
	}
}

void effect_woman(void)
{
	int w, h;
	w = FreeImage_GetWidth(effect_data.right);
	h = FreeImage_GetHeight(effect_data.right);

	float *angles = malloc(w * h * sizeof(float)); //angles data
	BYTE* scaled_angles = (BYTE*)malloc(w * h); //scaled to [0, 255] angles data

	//FFT
	init_image_data(effect_data.rchg, gimage_data);
	fft_r2c(right_plan, gimage_data, gout_data);
	calc_fft_angle(gout_data, angles, w, h);
	scale_float_data(angles, scaled_angles, w * h);
	draw_right_data(angles, 1);

	//IFFT
	fft_build_from_angle(right_plan, angles, gimage_data, w, h);
	scale_float_data(gimage_data, scaled_angles, w * h);
	draw_right_data(scaled_angles, 2);

	free(angles);
	free(scaled_angles);
}

/*
 * char* mask[mask_h][mask_w] : 空间域滤波器
 * w, h: image width, height : 要处理的图像的尺寸
 * attr: mask is odd, even, neither
 * */
void show_freq_filter_image(char* mask, int mask_w, int mask_h, int w, int h,
	filter_sym_attr attr)
{
	//step1: cal P, Q
	int P, Q; //P = width, Q = height
	filter_freq_newsize(mask_w, mask_h, w, h, &P, &Q);

	//spatial domain "mask" to frequency domain "filter"
	fftwf_complex* filter;
	filter = spatial_filter_to_freq(mask, mask_w, mask_h, P, Q, attr);

	//filter image at frequency domain
	BYTE* image = malloc(w * h);
	init_image_datab(effect_data.right, image);
	float* filtered_image = malloc(w * h * sizeof(float));

	filter_freq_domain(image, w, h, filter, P, Q, filtered_image);

	//show filtered image
	scale_float_data(filtered_image, image, w * h);
	draw_right_data(image, 3); //show at pos 3

	//free resources
	fftwf_free(filter);
	free(image);
	free(filtered_image);
}

/* example 4.15
 * 由小空间模板得到频率域滤波器
 *
 * in: 已知空间域的滤波器
 * out: 频率域的滤波器
 * 展示频域滤波器的透视图；
 * 频域滤波和空间域滤波的结果：应该相同
 * 1. Fig0439(a).tif
 * 2. 频谱
 * 3. 频率域滤波的结果
 * 4. 空间滤波器滤波的结果
 * */
void effect_spatial2_freq(void)
{
	int w, h;
	w = FreeImage_GetWidth(effect_data.right);
	h = FreeImage_GetHeight(effect_data.right);
	//show spectrum
	BYTE* spectrum = (BYTE*)malloc(w * h);
	float *s = malloc(w * h * sizeof(float));

	//show figure 1：Fig0439(a).tif
	char path[256];
	get_full_path(IMAGE_PATH, "Fig0439(a).tif", path);
	FIBITMAP* ori = open_img(path);
	draw_right_image(ori, 1);
	close_img(ori);

	//show figure 2：频谱
	calc_scaled_spectrum(effect_data.right, s, spectrum, 1, FFT_SHOW_LOG);
	draw_right_data(spectrum, 2);

	//show figure 4: 空间域滤波结果
	char mask[9] = {
		-1, 0, 1,
		-2, 0, 2,
		-1, 0, 1};
	image_filter_mask(effect_data.right, effect_data.rchg, 3, mask,\
		effect_data.rchg_data);
	image_filter_scale_show(effect_data.rchg, effect_data.rchg_data);
	draw_right_image(effect_data.rchg, 4);

	free(spectrum);
	free(s);

	//show figure 3：频域滤波器的图像
	char mask_fill[16] = {
		0, 0,  0, 0,
		0, -1, 0, 1,
		0, -2, 0, 2,
		0, -1, 0, 1};
	show_freq_filter_image(mask_fill, 4, 4, w, h, SYM_ATTR_ODD);
}

void special_effect(int cmd)
{
	//repeate press same key
	if (effect_data.cmd == cmd)
		return;

	if(cmd <= MAX_CMD_NUM) {
		effect_data.cmd = cmd;
		hint_right = (char*)command_str_en[cmd - 1];
		SetWindowTitle(command_str_cn[cmd - 1]);
		printf("%s\n", command_str_cn[cmd - 1]);
	}

	switch (cmd) {
	case 1:
		hint_right = "spectrum: 4.24, press key space";
		effect_rectangle();
		gstate = STATE_WAIT_NEXT;
		break;
	case 2:
		switch_next_image(woman_image, 4);
		effect_woman();
		break;
	case 3:
		switch_next_image(spatial2freq_image, 4);
		effect_spatial2_freq();
		break;
	case 4: //low pass filter
		switch_next_image(lp_image, 4);
		effect_lowpass();
		break;
	case 5: //high pass filter
		switch_next_image(hp_thumb, 4);
		effect_highpass();
		break;
	case 6:
		switch_next_image(bh_notch, 4);
		effect_notch();
		break;
	case KEY_DOWN:
		handle_key_down();
		break;
	case KEY_UP:
		handle_key_up();
		break;
	case KEY_SPACE:
		handle_key_space();
		break;
	default:
		hint_right = "not support command";
		break;
	}//end switch
}


int main(int argc, char** argv)
{
	// Initialization
	//--------------------------------------------------------------------------------------
	//test_2d_r2c();
	//test_dft2();
	//test_2d_c2c();

	FreeImage_Initialise(TRUE);
	init_effect_data();
	init_fb();

	InitWindow(screenWidth, screenHeight, "频域变换");
	// NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required)
	SetTargetFPS(60);               // Set our game to run at 60 frames-per-second
	//--------------------------------------------------------------------------------------

	int key = 0;
	int change = 0;
	Vector2 mouse = GetMousePosition();
	hint_right = "press number key";
	print_info_cn(command_str_cn, MAX_CMD_NUM);

	// Main game loop
	while (!WindowShouldClose())    // Detect window close button or ESC key
	{
		// Update
		key = GetKeyPressed();
		if (key >= '1' && key <= '9') {
			change = 1;
			key = key - '0';
		} else if(key == KEY_DOWN || key == KEY_UP){
			change = 1;
		}
		else if(key == KEY_SPACE) {
			change = 1;
		}
		else if (key == ESC_KEY) {
			break;
		}

		if (change) {
			change = 0;
			special_effect(key);
		}
		//----------------------------------------------------------------------------------
		//----------------------------------------------------------------------------------

		// Draw
		//----------------------------------------------------------------------------------
		BeginDrawing();
		ClearBackground(RAYWHITE);

		DrawText(hint_left, effect_data.startx, 5, 20, BLACK);
		if (hint_right) {
			DrawText(hint_right, effect_data.rx, 0, 20, BLACK);
		}
		show_info_en(command_str_en, MAX_CMD_NUM, effect_data.startx,\
			effect_data.left_max + effect_data.starty + 20);
		draw_image(effect_data.frame_buf, effect_data.win_width, effect_data.win_height);
		DrawLine(effect_data.split_line, effect_data.starty,\
			effect_data.split_line, GetScreenHeight(), GRAY);

		if (effect_data.cmd == 3) { //spatial to frequency domain
			draw_title("spatial mask", 1);
			draw_title("spectrum", 2);
			draw_title("freq filter", 3);
			draw_title("spatial filter", 4);
		} else if (effect_data.cmd == 4) { //low pass filter
			draw_title("r=10", 1);
			draw_title("r=30", 2);
			draw_title("r=60", 3);
			draw_title("r=460", 4);
		} else if(effect_data.cmd == 5) { //high pass filter
			if(effect_data.order == 1){
				draw_title("Butterworth", 1);
				draw_title("thresholding", 2);
			} else if(effect_data.order == 3) {
				draw_title("Gaussian", 1);
				draw_title("Highboost", 2);
				draw_title("Histogram equalized", 3);
			}
		} else if(effect_data.cmd == 6) { //Notch filter
			draw_title("original spectrum", 1);
			draw_title("filter * spectrum", 2);
			draw_title("filtered image", 3);
			draw_title("filtered spectrum", 4);
		}


		mouse = GetMousePosition();
		DrawText(TextFormat("mouse(%d, %d)", (int)mouse.x, (int)mouse.y), \
			GetScreenWidth() - 200, 10, 20, BLACK);

		EndDrawing();
		//----------------------------------------------------------------------------------
	}

	// De-Initialization
	destroy_effect();
	FreeImage_DeInitialise();

	//--------------------------------------------------------------------------------------
	CloseWindow();        // Close window and OpenGL context
	//--------------------------------------------------------------------------------------

	return 0;
}


